<template>
  <div class="pdf-marking">
    <div class="tool-box" :style="{height:toolboxHeight}">
      <div class="tool-box__item" @click="skipPage(9)">跳转到10页</div>
      <div class="tool-box__item" :class="{active:isAddXc}" @click="isAddXc=!isAddXc">添加瑕疵</div>
      <div class="tool-box__item" :class="{active:isSelectText}" @click="isSelectText=!isSelectText">选择文本</div>
    </div>
    <div class="container-box" ref="containerBox">
      <div class="container-box__content"
           ref="containerBoxContent"
           @mousedown="handleContainerBoxMousedown"
           @touchstart="handleContainerBoxTouchstart"
           @scroll="handleScroll">
        <div class="page"
             ref="page"
             :class="`page-${item.pageIndex}`"
             :style="{
               width:item.size.width+'px',
               height:item.size.height+'px',
               zoom:scale
             }"
             v-show="item.$img"
             v-for="item in dataList">
          <img class="img" :src="item.$img" :alt="'page'+item.pageIndex"
               @error="handleImgError($event,item)"
               @load="handleImgLoaded($event,item)" ondragstart="return false"/>
          <v-stage class="canvas" :config="{
            width:item.size.width,
            height:item.size.height
          }">
            <v-layer>
              <v-text :config="{text:'aaaaaaaaaaaaaaaa'}"/>
            </v-layer>
          </v-stage>
          <!--标记-->
          <div :style="getMarkStyle(mark)"
               @mousedown.prevent="handleMarkMousedown(mark)"
               @touchstart.prevent="handleMarkMousedown(mark)"
               v-for="mark in markShowList[item.pageIndex]"></div>

          <div class="page__page-index">{{item.pageIndex+1}} / {{dataList.length}}</div>
        </div>
        <vue-resize-sensor @resize="handleContainerBoxWidthResize"/>
      </div>
      <vue-resize-sensor initial @resize="handleContainerBoxResize"/>
    </div>
    <div class="debugger-info" :style="{top:`calc(200px + ${toolboxHeight})`}">
      <div class="debugger-info__item">当前比例：{{scale}}</div>
      <div class="debugger-info__item">当前滚动高度：{{scrollTop}}</div>
      <div class="debugger-info__item">当前进度：{{progress}}</div>
    </div>
  </div>
</template>

<script>
  import vueResizeSensor from 'vue-resize-sensor'
  import TextUtil from '../util/textUtil'
  import {openMask, uuid} from "../util/util";

  import VueKonva from "@/components/vue-konva";

  const {vStage, vLayer, vText} = VueKonva

  export default {
    components: {
      vueResizeSensor,
      vStage, vLayer, vText
    },
    props: {
      toolboxHeight: {
        type: String,
        default: '30px'
      },
      selectionBgColor: {
        type: String,
        default: 'rgba(0,180,255,0.5)'
      },
      imageLoadFn: Function,
      textLoadFn: Function,
      getImgAndText: Function,
    },
    data() {
      return {
        scaleType: 'page-width',// page-fit  page-width
        maxWidth: 0,
        maxHeight: 0,
        dataList: [],
        containerBoxSize: {width: 0, height: 0},
        scrollTop: 0,
        scrollHeight: 0,
        textUtil: null,
        markList: [],
        markShowList: {},
        isSelectText: false,
        isAddXc: false,
        isDeleteXc: false,
      }
    },
    computed: {
      progress() {
        if (!this.scrollHeight) return 1
        return this.scrollTop / this.scrollHeight
      },
      scale() {
        if (!this.maxHeight || !this.maxWidth) return 1
        if (this.scaleType === 'page-fit') return Math.min(this.containerBoxSize.height / this.maxHeight, this.containerBoxSize.width / this.maxWidth)
        if (this.scaleType === 'page-width') return this.containerBoxSize.width / this.maxWidth
      }
    },
    watch: {
      isAddXc(val) {
        if (!val) return
        // this.isAddXc = false
        this.isSelectText = false
        this.isDeleteXc = false
      },
      isSelectText(val) {
        if (!val) return
        this.isAddXc = false
        // this.isSelectText = false
        this.isDeleteXc = false
      },
      isDeleteXc(val) {
        if (!val) return
        this.isAddXc = false
        this.isSelectText = false
        // this.isDeleteXc = false
      },
    },
    methods: {
      getOffsetTop() {
        let offsetTop = 0
        let el = this.$refs.containerBox
        do offsetTop += el.offsetTop
        while ((el = el.parentElement))
        return offsetTop
      },
      getPointerPositionOnStage(e = event) {
        if (e.changedTouches) e = e.changedTouches[0]
        // console.log(e)
        return {
          x: e.layerX || e.pageX,
          y: e.layerY || (e.pageY - this.getOffsetTop())
        }
      },
      getPointerPositionOnImage(e) {
        let pageIndex = this.getPageIndexByPointerPosition(e)
        let stagePos = this.getPointerPositionOnStage(e)
        return this.posOnStageToImage(pageIndex, stagePos)
      },
      posOnStageToImage(pageIndex, stagePos) {
        let page = this.$refs.page[pageIndex]
        if (!page) return {x: 0, y: 0}
        let x = stagePos.x / this.scale - page.offsetLeft
        let y = (stagePos.y + this.scrollTop) / this.scale - page.offsetTop
        if (x < 0) x = 0
        else if (x > page.offsetWidth) x = page.offsetWidth
        if (y < 0) y = 0
        else if (y > page.offsetHeight) y = page.offsetHeight
        return {x, y}
      },
      getPageIndexByPointerPosition(e) {
        let stagePos = this.getPointerPositionOnStage(e)
        let pages = this.$refs.page
        if (!pages) return -1
        let pageIndex = pages.findIndex((page, idx) => {
          let start = page.offsetTop * this.scale
          let end = start + page.offsetHeight * this.scale
          return this.scrollTop + stagePos.y >= start && this.scrollTop + stagePos.y < end
        })
        // if (pageIndex < 0) pageIndex = 0
        return pageIndex
      },
      // test(e) {
      //   let pageIndex = this.getPageIndexByPointerPosition()
      //   let imgPos = this.getPointerPositionOnImage()
      //   console.log(this.textUtil.getWordByImgPos(pageIndex, imgPos))
      // },
      handleScroll() {
        this.$nextTick(() => {
          let target = this.$refs.containerBoxContent
          this.scrollTop = target.scrollTop
          this.scrollHeight = target.scrollHeight - this.containerBoxSize.height
        })
      },
      skipPage(pageIndex) {
        this.$nextTick(() => {
          // console.log(pageIndex)
          let page = this.$refs.page[pageIndex]
          if (page) page.scrollIntoView({block: "nearest", behavior: "smooth"})
        })
      },
      handleContainerBoxTouchstart(e) {
        this.clearSelection()
        if (this.isSelectText) {
          e.preventDefault()
          this.handleSelectText()
        } else if (this.isDeleteXc) {
          e.preventDefault()
          this.handleDeleteXc()
        } else if (this.isAddXc) {
          e.preventDefault()
          this.handleAddXc()
        } else {
          // console.log()
          e.changedTouches && (e = e.changedTouches[0])

          let startPageY = e.pageY
          let deltaY = 0

          if (this.scrollTop === 0) {

          }

          let _move = e => {
            e.changedTouches && (e = e.changedTouches[0])
            deltaY = e.pageY - startPageY
            console.log('touchmove')
          }
          let _up = e => {
            console.log('touchend', deltaY)
            if (Math.abs(deltaY) > 500) {
              if (deltaY > 0) {
                // console.log('上一页')
                if (this.scrollTop === 0) this.sendEvent('swipe-down')
              } else {
                // console.log('下一页')
                if (this.scrollHeight === this.scrollTop) this.sendEvent('swipe-up')
              }
            }
            window.removeEventListener("touchmove", _move)
            window.removeEventListener("touchend", _up)
          }
          window.addEventListener("touchmove", _move)
          window.addEventListener("touchend", _up)

          // scrollTop=0可向上翻页
          // scrollTop=scrollHeight 可向下翻页

          // this.scrollTop / this.scrollHeight
          // let move = e => {
          //
          // }
          // let up = e => {
          //   let deltaY = e.pageY - startPageY
          //   if (Math.abs(deltaY) > 500) {
          //     if (deltaY > 0) {
          //       // console.log('上一页')
          //       if (this.scrollTop === 0) this.sendEvent('swipe-down')
          //     } else {
          //       // console.log('下一页')
          //       if (this.scrollHeight === this.scrollTop) this.sendEvent('swipe-up')
          //     }
          //   }
          // }
          // if (this.scrollTop === 0 || this.scrollHeight === this.scrollTop) this.openMask(move, up)

        }
      },
      handleContainerBoxMousedown() {
        this.clearSelection()
        if (this.isAddXc) {
          this.handleAddXc()
        } else if (this.isDeleteXc) {
          this.handleDeleteXc()
        } else {
          this.handleSelectText()
        }
      },
      handleDeleteXc() {
      },
      handleMarkMousedown(mark) {
        if (this.isDeleteXc) {
          if (mark.mark.type === 'xiaci') {
            this.sendEvent('delete-xc', mark.mark)
          }
        }
        // console.log(mark.mark.type, event)
      },
      clearSelection() {
        this.removeMark('selection-mark')
      },
      handleSelectText() {
        let pageIndex = this.getPageIndexByPointerPosition()
        let imgPos = this.getPointerPositionOnImage()
        let A = this.textUtil.getWordByImgPos(pageIndex, imgPos)
        let move = e => {
          let pageIndex = this.getPageIndexByPointerPosition()
          let imgPos = this.getPointerPositionOnImage()
          let B = this.textUtil.getWordByImgPos(pageIndex, imgPos)
          if (!A) A = B

          if (!A || !B) return console.log(A, B);

          let pos = this.textUtil.getPos(A, B)
          if (!pos) return

          this.addMark({
            markid: 'selection-mark',
            start: pos.start,
            end: pos.end,
            config: {
              stroke: '',
              strokeWidth: 0,
              fill: this.selectionBgColor,
              name: 'selection'
            }
          })

        }
        let up = e => {

        }
        this.openMask(move, up)
      },
      handleAddXc() {
        let startP = this.getPointerPositionOnStage()
        let startX = startP.x
        let startY = startP.y

        let redMask = document.createElement('div')
        redMask.style.backgroundColor = 'rgba(255,0,0,0.3)'
        redMask.style.boxSizing = 'border-box'
        redMask.style.border = '1px solid red'
        redMask.style.position = 'absolute'
        redMask.style.left = `${startX}px`
        redMask.style.top = `${startY}px`

        this.$refs.containerBox.appendChild(redMask)


        let width = 0
        let height = 0

        let x = startX
        let y = startY

        let startPageIndex = this.getPageIndexByPointerPosition()
        let pageIndex = startPageIndex

        let move = e => {
          let p = this.getPointerPositionOnStage()
          width = p.x - startP.x
          height = p.y - startP.y

          pageIndex = Math.min(startPageIndex, this.getPageIndexByPointerPosition())

          x = startX
          y = startY

          if (width < 0) {
            x = startX + width
            width *= -1
          }
          if (height < 0) {
            y = startY + height
            height *= -1
          }

          redMask.style.left = `${x}px`
          redMask.style.top = `${y}px`
          redMask.style.width = `${width}px`
          redMask.style.height = `${height}px`
        }
        let up = e => {
          redMask.remove()
          let res = []
          for (let i = pageIndex; i < pageIndex + 5; i++) {

            let leftTopPos = this.posOnStageToImage(i, {x, y})
            let rightBottomPos = this.posOnStageToImage(i, {x: x + width, y: y + height})

            // console.log(x, y, width, height)
            // console.log(i, leftTopPos, rightBottomPos)
            let rect = {
              x: leftTopPos.x,
              y: leftTopPos.y,
              width: rightBottomPos.x - leftTopPos.x,
              height: rightBottomPos.y - leftTopPos.y,
            }
            if (rect.width && rect.height) {
              // console.log(rect, i)
              // this.addMark({
              //   start: i,
              //   end: JSON.stringify(rect)
              // })
              res.push({
                start: i,
                end: JSON.stringify(rect),
                // type: 'xiaci'
              })
            }
          }
          this.sendEvent('rect-draw-complete', res)
        }
        this.openMask(move, up)

      },
      sendEvent() {
        this.$emit(...arguments)
      },
      handleImgError(ev, item) {
        console.log(ev)
      },
      handleImgLoaded(ev, item) {
        let img = ev.target
        // console.dir(img)
        let naturalWidth = img.naturalWidth
        let naturalHeight = img.naturalHeight
        if (naturalWidth > this.maxWidth) this.maxWidth = naturalWidth
        if (naturalHeight > this.maxHeight) this.maxHeight = naturalHeight
        item.size = {
          width: naturalWidth,
          height: naturalHeight
        }
        this.handleScroll()
        // console.log(item.pageIndex, '图片加载完成')
      },
      handleContainerBoxWidthResize(size) {
        // console.log(size.width)
        this.containerBoxSize.width = size.width
      },
      handleContainerBoxResize(size) {
        this.containerBoxSize.height = size.height
        this.containerBoxSize.width = size.width - 17
      },
      async open({data}) {
        this.markList = []
        this.dataList = []
        this.isDeleteXc = false
        this.isAddXc = false
        this.isSelectText = false

        let resData = []
        for (let i = 0; i < data.map(item => ({...item})).length; i++) {
          let item = data[i]
          let res = {
            img: item.img,
            text: item.text
          }
          if (this.getImgAndText) res = await this.getImgAndText(i, item)
          // console.log(res)
          resData.push({
            ...item,
            $img: res.img,
            $text: res.text,
            pageIndex: i,
            size: {width: 0, height: 0}
          })
        }
        this.dataList = resData
        this.textUtil = new TextUtil(this.dataList)
        // this.dataList = data.map((item, pageIndex) => {
        //   return {}
        // })
      },
      openMask(move = () => ({}), up = () => ({})) {
        openMask(move, up, this.$refs.containerBox)
        // let mask = document.createElement('div')
        // mask.style.backgroundColor = 'rgba(0,0,0,0)'
        // mask.style.position = 'absolute'
        // mask.style.left = 0
        // mask.style.top = 0
        // mask.style.right = 0
        // mask.style.bottom = 0
        // this.$refs.containerBox.appendChild(mask)
        //
        // let $move = e => {
        //   move(e)
        // }
        // let $up = e => {
        //   removeEventListener('mouseup', $up)
        //   removeEventListener('mousemove', $move)
        //   mask.remove()
        //   up(e)
        // }
        // addEventListener('mousemove', $move)
        // addEventListener('mouseup', $up)
      },
      getMarkStyle(item) {
        // console.log(item)
        return {
          position: 'absolute',
          pointerEvents: 'all',
          left: item.x + 'px',
          top: item.y + 'px',
          width: item.width + 'px',
          height: item.height + 'px',
          backgroundColor: item.fill,
          borderColor: item.stroke,
          borderWidth: (item.strokeWidth || (item.stroke ? 4 : 0)) + 'px',
          borderStyle: 'solid',
          boxSizing: 'border-box'
        }
      },
      setPointerType() {
      },
      removeMark(markid) {
        for (let p in this.markShowList) {
          let marks = this.markShowList[p]
          for (let i = 0; i < marks.length; i++) {
            if (marks[i].mark.markid === markid) {
              marks.splice(i, 1)
              i--
            }
          }
        }
        let index = this.markList.findIndex(item => item.markid === markid)
        this.markList.splice(index, 1)
      },
      addMark(mark) {
        mark = JSON.parse(JSON.stringify(mark))
        if (!mark.markid) mark.markid = uuid()
        // if (!mark.markline) mark.markline = {}
        if (!mark.config) mark.config = {}
        // let index = this.markList.findIndex(item => item.markid === mark.markid)
        this.removeMark(mark.markid)
        // if (index > -1) {
        //   this.markList.splice(index, 1, mark)
        // } else {
        this.markList.push(mark)

        // if (!arr[p]) arr[p] = []
        // arr[p].push(_item)
        // }

        let marks = this.getMarksByMark(mark)
        for (let p in marks) {
          if (!this.markShowList[p]) this.$set(this.markShowList, p, [])
          this.markShowList[p].push(...marks[p])
        }
      },
      getMarksByMark(item) {
        let arr = {}
        // let $pageIndex = Number(item.start)
        // if (isNaN($pageIndex)) {
        //   let startIndex = ''
        //   let endIndex = ''
        //   if (/^(\d+)-(\d+)$/.test(item.start)) startIndex = Number(RegExp.$1)
        //   if (/^(\d+)-(\d+)$/.test(item.end)) endIndex = Number(RegExp.$1)
        //   if (pageIndex >= startIndex && pageIndex <= endIndex) {
        //     $pageIndex = pageIndex
        //   }
        // }
        // if ((typeof $pageIndex !== 'number') || ($pageIndex !== pageIndex)) {
        //   // console.log(pageIndex, '跳过这个')
        //   continue
        // }
        // let show = this.alwaysShowMarkTypes.indexOf(item.type) > -1
        // if (!this.markShow && item.config.name !== 'selection') continue
        // item.config.name==='selection'
        let A = this.textUtil.getWordByIndexPos(item.start)
        let B = this.textUtil.getWordByIndexPos(item.end)
        let tRows = this.textUtil.getWrodsAToB(A, B)
        if (tRows) {
          let text = ''
          let rows = Object.keys(tRows)
          let total = rows.length
          rows.map((name, idx) => {
            let $item = tRows[name]
            text += `${$item.text}\n`
            // if ($item.page === pageIndex) {
            let _item = {
              ...item.config,
              x: $item.x,
              y: $item.y,
              width: $item.width,
              height: $item.height,
              mark: item,
              currIdx: idx,
              total
            }
            if (_item.strokeWidth) {
              // _item.strokeWidth = _item.strokeWidth / this.imageGroupConfig.scale.x / this.scale
            }
            if ($item.height < 0) {
              _item.y = _item.y + $item.height
              _item.height = Math.abs(_item.height)
            }
            if (!_item.fill && !_item.stroke) {
              _item.fill = 'rgba(255,0,0,0.3)'
            }
            // if (item.config.type === 'underline') {
            //   // console.log(_item.height)
            //   _item.y = _item.y + _item.height
            //   _item.height = 0
            // }
            if (!arr[$item.page]) arr[$item.page] = []
            arr[$item.page].push(_item)
            // }
          })
          // for (let name in tRows) {
          //   let $item = tRows[name]
          //   text += `${$item.text}\n`
          //   if ($item.page === this.pageIndex) {
          //     let _item = {
          //       ...item.config,
          //       x: $item.x,
          //       y: $item.y,
          //       width: $item.width,
          //       height: $item.height,
          //       mark: item,
          //       currIdx: curr
          //     }
          //     if (_item.strokeWidth) {
          //       _item.strokeWidth = _item.strokeWidth / this.imageGroupConfig.scale.x / this.scale
          //     }
          //     if ($item.height < 0) {
          //       _item.y = _item.y + $item.height
          //       _item.height = Math.abs(_item.height)
          //     }
          //     if (!_item.fill && !_item.stroke) {
          //       _item.fill = 'rgba(255,0,0,0.3)'
          //     }
          //     // if (item.config.type === 'underline') {
          //     //   // console.log(_item.height)
          //     //   _item.y = _item.y + _item.height
          //     //   _item.height = 0
          //     // }
          //     arr.push(_item)
          //   }
          // }
          item.text = text.substr(0, text.length - 1)
        } else {
          try {
            let _item = {
              ...item.config,
              ...JSON.parse(item.end),
              mark: item
            }
            if (!_item.fill && !_item.stroke) {
              _item.stroke = 'rgba(255,0,0,1)'
            }
            let p = Number(item.start)
            if (!arr[p]) arr[p] = []
            arr[p].push(_item)
          } catch (e) {
            console.error('被吃掉的错误', e)
          }
        }
        return arr
      }
    }
  }
</script>
<style scoped lang="scss">
  @import "src/components/Marking/src/pdf-marking";

  .debugger-info {
    pointer-events: none;
    position: absolute;
    top: 0;
    left: 0;

    &__item {

    }
  }
</style>
